#pragma once
#include<iostream>
#include<vector>
#include<queue>
#include<unistd.h>
 #include"Task.hpp"
struct ThreadInfo
{
    pthread_t tid;
    std::string name;
};

static const int defalutnum = 5;
template<class T>
class ThreadPool 
{
public:
  void Lock()
    {
        pthread_mutex_lock(&mutex_);
    }
    void Unlock()
    {
        pthread_mutex_unlock(&mutex_);
    }
    void Wakeup() //唤醒
    {
        pthread_cond_signal(&cond_);
    }
    void ThreadSleep()
    {
        pthread_cond_wait(&cond_, &mutex_);
    }
      std::string GetThreadName(pthread_t tid)
    {
        for (const auto &ti : threads_)
        {
                 if (ti.tid == tid)
                return ti.name;
        }
        return "None";
    }


    public:
ThreadPool(int num = defalutnum) 
:threads_(num)
{
pthread_mutex_init(&mutex_ ,nullptr) ;
pthread_cond_init(&cond_,nullptr);
}


//不加static ,HandlerTask函数是类的成员函数 ，void *HandlerTask(ThreadPool * this ,void *args) 
//与pthread_create的参数  ，void *(*start_routine) (void *) ,参数个数不一致
//加了static，HandlerTask就不是类的成员函数
    static void *HandlerTask(void *args) 
    {
       
        ThreadPool<T> *tp  = (   ThreadPool<T> *)args;
         std::string name = tp->GetThreadName(pthread_self());
        while(true )
        {
            tp->Lock() ;
             while(tp->tasks_.empty() ) //用while循环，防止出现伪唤醒
             {
                //休眠
                tp->ThreadSleep();
             }
             //队列不为空 
             T t = tp->tasks_.front() ;
             tp->tasks_.pop() ;
        
            tp->Unlock() ;
            //线程从队列中拿到任务，这个任务已经是线程私有的，在处理任务时，不需要加锁 
          t() ;

          
        }
    }
       void Start()
       {
        for( int i =0 ; i <threads_.size() ; i ++)
        {
            threads_[i].name = "thread-" + std::to_string(i + 1);
            pthread_create(&(threads_[i].tid ) , nullptr , HandlerTask,this) ;//this，传当前对象的指针
        }
       }
      void Push(const T &t)  //插入任务
      {
             Lock();
        tasks_.push(t);
        Wakeup();
        Unlock();

      }
    static ThreadPool<T> *GetInstance()
    {
        if (nullptr == tp_) // ???
        {
            pthread_mutex_lock(&lock_);
            if (nullptr == tp_)
            {
                std::cout << "log: singleton create done first!" << std::endl;
                tp_ = new ThreadPool<T>();
            }
            pthread_mutex_unlock(&lock_);
        }

        return tp_;
    }
   T Pop()  //拿任务出来
    {
        T t = tasks_.front();
        tasks_.pop();
        return t;
    }
        ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }
private:
  std::vector<ThreadInfo> threads_;
    std::queue<T> tasks_;

    pthread_mutex_t mutex_; //锁
    pthread_cond_t cond_;//条件变量

   static   ThreadPool<T> *tp_;
  static    pthread_mutex_t lock_;
};



template <class T>
ThreadPool<T> *ThreadPool<T>::tp_ = nullptr;

template <class T>
pthread_mutex_t ThreadPool<T>::lock_ = PTHREAD_MUTEX_INITIALIZER;